#include "selfAdaptionSkin.h"


selfAdaptionSkin::selfAdaptionSkin(void)
{
	BGhminBest = BGhmin;
	BGhmaxBest = BGhmax;
	BGvminBest = BGvmin;
	BGvmaxBest = BGvmax;
	BRminBest = BRmin;
	BRmaxBest = BRmax;
	GRminBest = GRmin;
	GRmaxBest = GRmax;

	BGhminOR = BGhmin;
	BGhmaxOR = BGhmax;
	BGvminOR = BGvmin;
	BGvmaxOR = BGvmax;
	BRminOR = BRmin;
	BRmaxOR = BRmax;
	GRminOR = GRmin;
	GRmaxOR = GRmax;
}


selfAdaptionSkin::~selfAdaptionSkin(void)
{
}

void selfAdaptionSkin::skinDetectLC(Mat& _img, Mat& _mask)
{
	int i, j;
	uchar* imgData = (uchar*)_img.data;
	uchar* maskData = (uchar*)_mask.data;
	for(i = 0; i < _img.rows; i++)
	{
		for (j = 0; j < _img.cols; j++)
		{
			if (1

				&& BGhminBest * ((int)imgData[(i * _img.cols + j) * 3 + 1]) + 
				BRminBest * ((int)imgData[(i * _img.cols + j) * 3 + 2]) < 
				((int)imgData[(i * _img.cols + j) * 3])

				&& ((int)imgData[(i * _img.cols + j) * 3]) <
				BGhmaxBest * ((int)imgData[(i * _img.cols + j) * 3 + 1]) +
				BRmaxBest * ((int)imgData[(i * _img.cols + j) * 3 + 2])

				&& BGvminBest * ((int)imgData[(i * _img.cols + j) * 3]) + 
				GRminBest * ((int)imgData[(i * _img.cols + j) * 3 + 2]) <
				((int)imgData[(i * _img.cols + j) * 3 + 1])

				&& ((int)imgData[(i * _img.cols + j) * 3 + 1]) <
				BGvmaxBest * ((int)imgData[(i * _img.cols + j) * 3]) +
				GRmaxBest * ((int)imgData[(i * _img.cols + j) * 3 + 2])

				&&(int)imgData[(i * _img.cols + j) * 3 + 2] >
				50
				)
			{

				maskData[i * _mask.cols + j] = (uchar)255;
			}

		}
	}
	
}

float selfAdaptionSkin::findFitnessMask(Mat& _img, Mat& _mask,
	float&_BGhmin,  float&_BGhmax, 
	float&_BGvmin, float&_BGvmax,
	float&_BRmin, float&_BRmax, 
	float&_GRmin, float&_GRmax)
{

	int i, j;
	int areaOfMask = 0;

	float skinMaskCount = 0;
	float BGMaskCount = 0;
	uchar*imgData = (uchar*)_img.data;
	uchar*maskData = (uchar*)_mask.data;


	for (i = 0; i < _img.rows; i++)
	{
		for (j = 0; j < _img.cols; j++)
		{
			if (1

				&& _BGhmin * ((int)imgData[(i * _img.cols + j) * 3 + 1]) + 
				_BRmin * ((int)imgData[(i * _img.cols + j) * 3 + 2]) < 
				((int)imgData[(i * _img.cols + j) * 3])

				&& ((int)imgData[(i * _img.cols + j) * 3]) <
				_BGhmax * ((int)imgData[(i * _img.cols + j) * 3 + 1]) +
				_BRmax * ((int)imgData[(i * _img.cols + j) * 3 + 2])

				&& _BGvmin * ((int)imgData[(i * _img.cols + j) * 3]) + 
				_GRmin * ((int)imgData[(i * _img.cols + j) * 3 + 2]) <
				((int)imgData[(i * _img.cols + j) * 3 + 1])

				&& ((int)imgData[(i * _img.cols + j) * 3 + 1]) <
				_BGvmax * ((int)imgData[(i * _img.cols + j) * 3]) +
				_GRmax * ((int)imgData[(i * _img.cols + j) * 3 + 2])

				&&(int)imgData[(i * _img.cols + j) * 3 + 2] >
				50
				)
			{
				if ((int)(maskData[i *_mask.cols + j]) > 0)
				{
					skinMaskCount = skinMaskCount + 1;
					areaOfMask++;
				}
				else
				{
					BGMaskCount = BGMaskCount + 1;
				}
			}
			else if ((int)(maskData[i * _mask.cols + j]) > 0)
			{
				areaOfMask++;
			}
		}
	}
	float fiter = 2 * skinMaskCount / areaOfMask - 
		BGMaskCount / ((float)(_img.rows * _img.cols - areaOfMask));
	return fiter;
}






float selfAdaptionSkin::findFitnessROI(Mat& _img, Rect& _ROI,
	float&_BGhmin,  float&_BGhmax, 
	float&_BGvmin, float&_BGvmax,
	float&_BRmin, float&_BRmax, 
	float&_GRmin, float&_GRmax)
{
	int i, j;
	float skinMaskCount = 0;
	float BGMaskCount = 0;
	uchar*imgData = (uchar*)_img.data;

	for (i = 0; i < _img.rows; i++)
	{
		for (j = 0; j < _img.cols; j++)
		{
			if (1

				&& _BGhmin * ((int)imgData[(i * _img.cols + j) * 3 + 1]) + 
				_BRmin * ((int)imgData[(i * _img.cols + j) * 3 + 2]) < 
				((int)imgData[(i * _img.cols + j) * 3])

				&& ((int)imgData[(i * _img.cols + j) * 3]) <
				_BGhmax * ((int)imgData[(i * _img.cols + j) * 3 + 1]) +
				_BRmax * ((int)imgData[(i * _img.cols + j) * 3 + 2])

				&& _BGvmin * ((int)imgData[(i * _img.cols + j) * 3]) + 
				_GRmin * ((int)imgData[(i * _img.cols + j) * 3 + 2]) <
				((int)imgData[(i * _img.cols + j) * 3 + 1])

				&& ((int)imgData[(i * _img.cols + j) * 3 + 1]) <
				_BGvmax * ((int)imgData[(i * _img.cols + j) * 3]) +
				_GRmax * ((int)imgData[(i * _img.cols + j) * 3 + 2])

				&&(int)imgData[(i * _img.cols + j) * 3 + 2] >
				50
				)
			{
				if (i >= _ROI.y && i < (_ROI.y + _ROI.height) && j >= _ROI.x && (j < _ROI.x + _ROI.width))
				{
					skinMaskCount = skinMaskCount + 1;
				}
				else
				{
					BGMaskCount = BGMaskCount + 1;
				}
			}
		}
	}
	float fiter = 2 * skinMaskCount / ((float)(_ROI.width * _ROI.height)) - 
		BGMaskCount / ((float)(_img.rows * _img.cols - _ROI.width * _ROI.height));
	return fiter;
}



void selfAdaptionSkin::getBestParamentMask(Mat& _img, Mat& _mask)
{
	int i, j;
	float bestPara;

	int bestIdx = 0;
	bestPara = findFitnessMask(_img, _mask, 
		BGhminOR, BGhmaxOR, BGvminOR, BGvmaxOR, BRminOR, BRmaxOR, GRminOR, GRmaxOR);
	for (i = 0; i < 21; i++)
	{
		BRminBest = BRmin + 0.01 * i - 0.1;
		if (bestPara < findFitnessMask(_img, _mask,
			BGhminOR, BGhmaxOR, BGvminOR, BGvmaxOR, BRminBest, BRmaxOR, GRminOR, GRmaxOR))
		{
			bestPara = findFitnessMask(_img, _mask,
				BGhminOR, BGhmaxOR, BGvminOR, BGvmaxOR, BRminBest, BRmaxOR, GRminOR, GRmaxOR);
			bestIdx = i;
		}
	}
	BRminBest = BRmin + 0.01 * bestIdx - 0.1;
//	cout<<BRminBest<<ends;




	bestIdx = 0;
	for (i = 0; i < 21; i++)
	{
		BRmaxBest = BRmax + 0.01 * i - 0.1;
		if (bestPara < findFitnessMask(_img, _mask,
			BGhminOR, BGhmaxOR, BGvminOR, BGvmaxOR, BRminBest, BRmaxBest, GRminOR, GRmaxOR))
		{
			bestPara = findFitnessMask(_img, _mask,
				BGhminOR, BGhmaxOR, BGvminOR, BGvmaxOR, BRminBest, BRmaxBest, GRminOR, GRmaxOR);
			bestIdx = i;
		}
	}
	BRmaxBest = BRmax + 0.01 * bestIdx - 0.1;
//	cout<<BRmaxBest<<ends;





	bestIdx = 0;
	for (i = 0; i < 21; i++)
	{
		GRminBest = GRmin + 0.01 * i - 0.1;
		if (bestPara < findFitnessMask(_img, _mask,
			BGhminOR, BGhmaxOR, BGvminOR, BGvmaxOR, BRminBest, BRmaxBest, GRminBest, GRmaxOR))
		{
			bestPara = findFitnessMask(_img, _mask,
				BGhminOR, BGhmaxOR, BGvminOR, BGvmaxOR, BRminBest, BRmaxBest, GRminBest, GRmaxOR);
			bestIdx = i;
		}
	}
	GRminBest = GRmin + 0.01 * bestIdx - 0.1;
//	cout<<GRminBest<<ends;




	bestIdx = 0;
	for (i = 0; i < 21; i++)
	{
		GRmaxBest = GRmax + 0.01 * i - 0.1;
		if (bestPara < findFitnessMask(_img, _mask,
			BGhminOR, BGhmaxOR, BGvminOR, BGvmaxOR, BRminBest, BRmaxBest, GRminBest, GRmaxBest))
		{
			bestPara = findFitnessMask(_img, _mask,
				BGhminOR, BGhmaxOR, BGvminOR, BGvmaxOR, BRminBest, BRmaxBest, GRminBest, GRmaxBest);
			bestIdx = i;
		}
	}
	GRmaxBest = GRmax + 0.01 * bestIdx - 0.1;
//	cout<<GRmaxBest<<endl;

}





void selfAdaptionSkin::getBestParamentROI(Mat& _img, Rect& _ROI)
{
	int i, j;
	float bestPara;



	int bestIdx = 0;
	bestPara = findFitnessROI(_img, _ROI, 
		BGhminOR, BGhmaxOR, BGvminOR, BGvmaxOR, BRminOR, BRmaxOR, GRminOR, GRmaxOR);
	for (i = 0; i < 21; i++)
	{
		BRminBest = BRmin + 0.01 * i - 0.1;
		if (bestPara < findFitnessROI(_img, _ROI,
			BGhminOR, BGhmaxOR, BGvminOR, BGvmaxOR, BRminBest, BRmaxOR, GRminOR, GRmaxOR))
		{
			bestPara = findFitnessROI(_img, _ROI,
				BGhminOR, BGhmaxOR, BGvminOR, BGvmaxOR, BRminBest, BRmaxOR, GRminOR, GRmaxOR);
			bestIdx = i;
		}
	}
	BRminBest = BRmin + 0.01 * bestIdx - 0.1;
//	cout<<BRminBest<<ends;




	bestIdx = 0;
	for (i = 0; i < 21; i++)
	{
		BRmaxBest = BRmax + 0.01 * i - 0.1;
		if (bestPara < findFitnessROI(_img, _ROI,
			BGhminOR, BGhmaxOR, BGvminOR, BGvmaxOR, BRminBest, BRmaxBest, GRminOR, GRmaxOR))
		{
			bestPara = findFitnessROI(_img, _ROI,
				BGhminOR, BGhmaxOR, BGvminOR, BGvmaxOR, BRminBest, BRmaxBest, GRminOR, GRmaxOR);
			bestIdx = i;
		}
	}
	BRmaxBest = BRmax + 0.01 * bestIdx - 0.1;
//	cout<<BRmaxBest<<ends;





	bestIdx = 0;
	for (i = 0; i < 21; i++)
	{
		GRminBest = GRmin + 0.01 * i - 0.1;
		if (bestPara < findFitnessROI(_img, _ROI,
			BGhminOR, BGhmaxOR, BGvminOR, BGvmaxOR, BRminBest, BRmaxBest, GRminBest, GRmaxOR))
		{
			bestPara = findFitnessROI(_img, _ROI,
				BGhminOR, BGhmaxOR, BGvminOR, BGvmaxOR, BRminBest, BRmaxBest, GRminBest, GRmaxOR);
			bestIdx = i;
		}
	}
	GRminBest = GRmin + 0.01 * bestIdx - 0.1;
//	cout<<GRminBest<<ends;




	bestIdx = 0;
	for (i = 0; i < 21; i++)
	{
		GRmaxBest = GRmax + 0.01 * i - 0.1;
		if (bestPara < findFitnessROI(_img, _ROI,
			BGhminOR, BGhmaxOR, BGvminOR, BGvmaxOR, BRminBest, BRmaxBest, GRminBest, GRmaxBest))
		{
			bestPara = findFitnessROI(_img, _ROI,
				BGhminOR, BGhmaxOR, BGvminOR, BGvmaxOR, BRminBest, BRmaxBest, GRminBest, GRmaxBest);
			bestIdx = i;
		}
	}
	GRmaxBest = GRmax + 0.01 * bestIdx - 0.1;
//	cout<<GRmaxBest<<endl;

}